﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using StyleMVVM.View.Impl;
#if NETFX_CORE
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Data;

#else
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;

#endif

namespace StyleMVVM.View
{
	public sealed class TextChangedBinding
	{
		public static string GetPath(DependencyObject obj)
		{
			return (string)obj.GetValue(InternalPathProperty);
		}

		public static void SetPath(DependencyObject obj, string value)
		{
			obj.SetValue(InternalPathProperty, value);
		}

		public static DependencyProperty PathProperty
		{
			get { return InternalPathProperty; }
		}

		// Using a DependencyProperty as the backing store for Path.  This enables animation, styling, binding, etc...
		internal static readonly DependencyProperty InternalPathProperty =
			DependencyProperty.RegisterAttached("Path",
			                                    typeof(string),
			                                    typeof(TextChangedBinding),
			                                    new PropertyMetadata(null, PathChangedHandler));

		public static IValueConverter GetDataConverter(DependencyObject obj)
		{
			return (IValueConverter)obj.GetValue(InternalDataConverterProperty);
		}

		public static void SetDataConverter(DependencyObject obj, IValueConverter value)
		{
			obj.SetValue(InternalDataConverterProperty, value);
		}

		public static DependencyProperty DataConverterProperty
		{
			get { return InternalDataConverterProperty; }
		}

		// Using a DependencyProperty as the backing store for DataConverter.  This enables animation, styling, binding, etc...
		internal static readonly DependencyProperty InternalDataConverterProperty =
			DependencyProperty.RegisterAttached("DataConverter",
			                                    typeof(IValueConverter),
			                                    typeof(TextChangedBinding),
			                                    new PropertyMetadata(null, DataConverterChanged));

		private static void PathChangedHandler(DependencyObject d, DependencyPropertyChangedEventArgs e)
		{
			TextBox textBox = d as TextBox;

			if (textBox != null)
			{
				textBox.TextChanged -= TextBoxOnTextChanged;

				textBox.TextChanged += TextBoxOnTextChanged;

				ApplyBinding(textBox);
			}
			else
			{
				throw new ArgumentException("This can only be used on TextBox classes");
			}
		}

		private static void DataConverterChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
		{
			TextBox textBox = d as TextBox;

			if (textBox != null)
			{
				ApplyBinding(textBox);
			}
			else
			{
				throw new ArgumentException("This can only be used on TextBox classes");
			}
		}

		private static void TextBoxOnTextChanged(object sender, TextChangedEventArgs textChangedEventArgs)
		{
			TextBox textBox = (TextBox)sender;

			TextChangedBindingHelper.SetValue(textBox, textBox.Text);
		}

		private static void ApplyBinding(TextBox textBox)
		{
			string path = GetPath(textBox);

			if (!string.IsNullOrEmpty(path))
			{
				Binding newBinding = new Binding();

				newBinding.Mode = BindingMode.TwoWay;
				newBinding.Path = new PropertyPath(GetPath(textBox));
				newBinding.Converter = GetDataConverter(textBox);

				textBox.SetBinding(TextChangedBindingHelper.ValueProperty, newBinding);
			}
			else
			{
				textBox.SetBinding(TextChangedBindingHelper.ValueProperty, null);
			}
		}
	}
}